/*
 * AIEngine a new generation network intrusion detection system.
 *
 * Copyright (C) 2013-2023  Luis Campo Giralte
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 *
 * Written by Luis Campo Giralte <luis.camp0.2009@gmail.com> 
 *
 */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "NetworkStack.h"
#include "StackLan.h"
#include "StackLanIPv6.h"
#include "StackMobile.h"
#include "StackVirtual.h"
#include "StackOpenFlow.h"
#include "StackMobileIPv6.h"
#include "PacketDispatcher.h"
#include "NetworkStack.h"
#include "StringCache.h"
#include "Cache.h"
#include "protocols/frequency/FrequencyGroup.h"
#include "regex/Regex.h"
#include "learner/LearnerEngine.h"
#include "names/DomainNameManager.h"
#include "Signature.h"
#include "DatabaseAdaptor.h"
#include "ipset/IPSet.h"
#include "ipset/IPRadixTree.h"
#include "ipset/IPBloomSet.h"
#include "ipset/IPSetManager.h"
#include "python_help.h"
#include <boost/python.hpp>
#include <boost/python/def.hpp>
#include <boost/python/module_init.hpp>
#include <boost/python/docstring_options.hpp>
#include <boost/asio.hpp>
#include <Python.h> // compatibility

using namespace boost::python;
using namespace aiengine;

struct DatabaseAdaptorWrap: DatabaseAdaptor, wrapper<DatabaseAdaptor>
{
        void connect(std::string &connection_str) { this->get_override("connection")(connection_str); }
        void insert(const std::string &key) { this->get_override("insert")(key); }
        void update(const std::string &key, const std::string& data) { this->get_override("update")(key, data); }
        void remove(const std::string &key) { this->get_override("remove")(key); }
};

BOOST_PYTHON_MODULE(pyaiengine)
{
        using namespace std;
	using namespace boost::asio;
	using self_ns::str;

#if defined(HAVE_PYTHON_GIL)
	if (! PyEval_ThreadsInitialized()) {
    		PyEval_InitThreads();
		PyEval_ReleaseLock();
	}
#endif

	// Enable de documentation, for help(pyaiengine)
	boost::python::docstring_options doc_options(true, true, false);

        // for overload the methods with the class
	void (NetworkStack::*setDomainNameManager1)(const SharedPointer<DomainNameManager>&, const std::string&) = 		&NetworkStack::setDomainNameManager;
	void (NetworkStack::*setDomainNameManager2)(const SharedPointer<DomainNameManager>&, const std::string&, bool) = 	&NetworkStack::setDomainNameManager;
	void (NetworkStack::*setTCPDatabaseAdaptor1)(boost::python::object&) = 		&NetworkStack::setTCPDatabaseAdaptor;
	void (NetworkStack::*setTCPDatabaseAdaptor2)(boost::python::object&, int) = 	&NetworkStack::setTCPDatabaseAdaptor;
	void (NetworkStack::*setUDPDatabaseAdaptor1)(boost::python::object&) = 		&NetworkStack::setUDPDatabaseAdaptor;
	void (NetworkStack::*setUDPDatabaseAdaptor2)(boost::python::object&, int) = 	&NetworkStack::setUDPDatabaseAdaptor;
	void (NetworkStack::*statisticsByProtocol1)(const std::string&) const = 	&NetworkStack::statistics;
	void (NetworkStack::*statisticsByProtocol2)(int) const = 			&NetworkStack::statistics;
	void (NetworkStack::*statisticsByProtocol3)(const std::string&, int) const = 	&NetworkStack::statistics;
	void (NetworkStack::*statistics)() const = 					&NetworkStack::statistics;
	void (NetworkStack::*releaseCache)(const std::string&) =			&NetworkStack::releaseCache;
	void (NetworkStack::*releaseCaches)() =						&NetworkStack::releaseCaches;
	void (NetworkStack::*increaseAllocatedMemory)(const std::string&, int) =	&NetworkStack::increaseAllocatedMemory;
	void (NetworkStack::*decreaseAllocatedMemory)(const std::string&, int) =	&NetworkStack::decreaseAllocatedMemory;
	boost::python::dict (NetworkStack::*getCounters)(const std::string&) =		&NetworkStack::getCounters;
	boost::python::dict (NetworkStack::*getCacheData)(const std::string&, const std::string&) =		&NetworkStack::getCacheData;
	SharedPointer<Cache<StringCache>> (NetworkStack::*getCacheByName)(const std::string&, const std::string&) =		&NetworkStack::getCache;
        void (NetworkStack::*setAnomalyCallback)(PyObject*, const std::string&) =	&NetworkStack::setAnomalyCallback;
	void (NetworkStack::*showProtocolSummaryReport)() const =			&NetworkStack::showProtocolSummary;
	void (NetworkStack::*setDynamicAllocatedMemoryOne)(bool) =			&NetworkStack::setDynamicAllocatedMemory;
	void (NetworkStack::*setDynamicAllocatedMemoryProto)(const std::string&, bool) = 	&NetworkStack::setDynamicAllocatedMemory;
	void (NetworkStack::*setOnFailCacheCallback)(const std::string&, PyObject*) =	&NetworkStack::setOnFailCacheCallback;

        boost::python::class_<NetworkStack, boost::noncopyable>("NetworkStack",
		"Abstract class that implements a common network stack.", no_init)
                .def("set_domain_name_manager", pure_virtual(setDomainNameManager1),
			help_set_domain_name_manager)
                .def("set_domain_name_manager", pure_virtual(setDomainNameManager2),
			help_set_domain_name_manager)
		.def("show", statisticsByProtocol1,
			help_show_statistics)
		.def("show", statisticsByProtocol2,
			help_show_statistics)
		.def("show", statisticsByProtocol3,
			help_show_statistics)
		.def("show", statistics,
			help_show_statistics)
		.def("increase_allocated_memory", pure_virtual(increaseAllocatedMemory),
			help_increase_alloc_mem)
		.def("decrease_allocated_memory", pure_virtual(decreaseAllocatedMemory),
			help_decrease_alloc_mem)
		.def("set_tcp_database_adaptor", pure_virtual(setTCPDatabaseAdaptor1))
		.def("set_tcp_database_adaptor", pure_virtual(setTCPDatabaseAdaptor2))
		.def("set_udp_database_adaptor", pure_virtual(setUDPDatabaseAdaptor1))
		.def("set_udp_database_adaptor", pure_virtual(setUDPDatabaseAdaptor2))
                .def("release_cache", pure_virtual(releaseCache),
			help_release_cache)
                .def("release_caches", pure_virtual(releaseCaches),
			help_releases_caches)
                .def("get_counters", pure_virtual(getCounters),
			help_get_counters)
                .def("reset_counters", &NetworkStack::resetCounters,
			help_reset_counters)
                .def("get_cache_data", pure_virtual(getCacheData))
                .def("get_cache", pure_virtual(getCacheByName),
			help_get_cache)
                .def("set_anomaly_callback", pure_virtual(setAnomalyCallback))
		.def("show_protocol_statistics", showProtocolSummaryReport)
		.def("set_dynamic_allocated_memory", setDynamicAllocatedMemoryOne)
		.def("set_dynamic_allocated_memory", setDynamicAllocatedMemoryProto)
		.def("show_anomalies", &NetworkStack::showAnomalies,
			help_show_anomalies)
		.def("enable_protocol", &NetworkStack::enableProtocol,
			help_enable_protocol)
		.def("disable_protocol", &NetworkStack::disableProtocol,
			help_disable_protocol)
		.def("attach_to", &NetworkStack::attachTo,
			help_attach_to)
                .def("show_flows", &NetworkStack::showSelectedFlows, (
                        boost::python::arg("src_ip")="",
                        boost::python::arg("src_port")=0,
                        boost::python::arg("protocol")=0,
                        boost::python::arg("l7protocol")="",
                        boost::python::arg("dst_ip")="",
                        boost::python::arg("dst_port")=0,
                        boost::python::arg("limit")=std::numeric_limits<int>::max()),
                        help_show_flows)
                .def("set_on_fail_cache_callback", pure_virtual(setOnFailCacheCallback),
			help_fail_cache_callback)
	;

	// Definitions for the StackLan class
	void (StackLan::*increaseAllocatedMemoryLan)(const std::string&, int) =		&StackLan::increaseAllocatedMemory;
	void (StackLan::*decreaseAllocatedMemoryLan)(const std::string&, int) =		&StackLan::decreaseAllocatedMemory;
        void (StackLan::*setDomainNameManagerLan1)(const SharedPointer<DomainNameManager>&, const std::string&) = 	&StackLan::setDomainNameManager;
        void (StackLan::*setDomainNameManagerLan2)(const SharedPointer<DomainNameManager>&, const std::string&, bool) =	&StackLan::setDomainNameManager;
	void (StackLan::*setTCPDatabaseAdaptorLan1)(boost::python::object&) = 		&StackLan::setTCPDatabaseAdaptor;
	void (StackLan::*setTCPDatabaseAdaptorLan2)(boost::python::object&, int) = 	&StackLan::setTCPDatabaseAdaptor;
	void (StackLan::*setUDPDatabaseAdaptorLan1)(boost::python::object&) = 		&StackLan::setUDPDatabaseAdaptor;
	void (StackLan::*setUDPDatabaseAdaptorLan2)(boost::python::object&, int) = 	&StackLan::setUDPDatabaseAdaptor;
	void (StackLan::*releaseCacheLan)(const std::string&) =				&StackLan::releaseCache;
	void (StackLan::*releaseCachesLan)() =						&StackLan::releaseCaches;
	boost::python::dict (StackLan::*getCountersLan)(const std::string&) =		&StackLan::getCounters;
	boost::python::dict (StackLan::*getCacheDataLan)(const std::string&, const std::string&) =		&StackLan::getCacheData;
	SharedPointer<Cache<StringCache>> (StackLan::*getCacheByNameLan)(const std::string&, const std::string&) =		&StackLan::getCache;
        void (StackLan::*setAnomalyCallbackLan)(PyObject*, const std::string&) =	&StackLan::setAnomalyCallback;
	void (StackLan::*setOnFailCacheCallbackLan)(const std::string&, PyObject*) = &StackLan::setOnFailCacheCallback;
	const char* (StackLan::*lanName)() const = 					&StackLan::name;

	boost::python::class_<StackLan, bases<NetworkStack> >("StackLan",
		"Class that implements a network stack for lan enviroments")
		.def_readonly("name", lanName,
			help_stack_name)
		.add_property("stats_level", &StackLan::getStatisticsLevel, &StackLan::setStatisticsLevel,
			help_stack_stats_level)
		.add_property("flows_timeout", &StackLan::getFlowsTimeout, &StackLan::setFlowsTimeout,
			help_stack_flows_timeout)
                .add_property("tcp_flows", &StackLan::getTotalTCPFlows, &StackLan::setTotalTCPFlows,
                        help_stack_tcp_flows)
                .add_property("udp_flows", &StackLan::getTotalUDPFlows, &StackLan::setTotalUDPFlows,
                       	help_stack_udp_flows) 
		.add_property("tcp_regex_manager", &StackLan::getTCPRegexManager, &StackLan::setTCPRegexManager,
                        help_stack_tcp_regex_manager)
		.add_property("udp_regex_manager", &StackLan::getUDPRegexManager, &StackLan::setUDPRegexManager,
                        help_stack_udp_regex_manager)
		.add_property("tcp_ip_set_manager", &StackLan::getTCPIPSetManager, &StackLan::setTCPIPSetManager,
			help_stack_tcp_ip_set_manager)
		.add_property("udp_ip_set_manager", &StackLan::getUDPIPSetManager, &StackLan::setUDPIPSetManager,
			help_stack_udp_ip_set_manager)
		.add_property("link_layer_tag", &StackLan::getLinkLayerTag, &StackLan::enableLinkLayerTagging,
			help_stack_link_layer_tag)
		.add_property("tcp_flow_manager", make_function(&StackLan::getTCPFlowManager, return_internal_reference<>()),
			help_stack_tcp_flow_manager)
		.add_property("udp_flow_manager", make_function(&StackLan::getUDPFlowManager, return_internal_reference<>()),
			help_stack_udp_flow_manager)
		.add_property("mode", &StackLan::getMode, &StackLan::setMode,
			help_operation_mode)
		.def("increase_allocated_memory", increaseAllocatedMemoryLan,
			help_increase_alloc_mem)
		.def("decrease_allocated_memory", decreaseAllocatedMemoryLan,
			help_decrease_alloc_mem)
                .def("set_domain_name_manager", setDomainNameManagerLan1,
			help_set_domain_name_manager)
                .def("set_domain_name_manager", setDomainNameManagerLan2,
			help_set_domain_name_manager)
		.def("set_tcp_database_adaptor", setTCPDatabaseAdaptorLan1,
			help_set_tcp_database_adaptor)
		.def("set_tcp_database_adaptor", setTCPDatabaseAdaptorLan2,
			help_set_tcp_database_adaptor)
		.def("set_udp_database_adaptor", setUDPDatabaseAdaptorLan1,
			help_set_udp_database_adaptor)
		.def("set_udp_database_adaptor", setUDPDatabaseAdaptorLan2,
			help_set_udp_database_adaptor)
		.def("release_cache", releaseCacheLan,
			help_release_cache)
		.def("release_caches", releaseCachesLan,
			help_releases_caches)
		.def("get_counters", getCountersLan, 
			help_get_counters)
		.def("get_cache_data", getCacheDataLan, 
			help_stack_get_cache_data)
		.def("get_cache", getCacheByNameLan, 
			help_get_cache)
                .def("set_anomaly_callback", setAnomalyCallbackLan,
			help_anomaly_callback)
                .def("set_on_fail_cache_callback", setOnFailCacheCallbackLan,
			help_fail_cache_callback)
	;

	// Definitions for the StackMobile class
	void (StackMobile::*increaseAllocatedMemoryMobile)(const std::string&, int) =		&StackMobile::increaseAllocatedMemory;
	void (StackMobile::*decreaseAllocatedMemoryMobile)(const std::string&, int) =		&StackMobile::decreaseAllocatedMemory;
        void (StackMobile::*setDomainNameManagerMobile1)(const SharedPointer<DomainNameManager>&, const std::string&) = 	&StackMobile::setDomainNameManager;
        void (StackMobile::*setDomainNameManagerMobile2)(const SharedPointer<DomainNameManager>&, const std::string&, bool) = 	&StackMobile::setDomainNameManager;
        void (StackMobile::*setTCPDatabaseAdaptorMobile1)(boost::python::object&) =     	&StackMobile::setTCPDatabaseAdaptor;
        void (StackMobile::*setTCPDatabaseAdaptorMobile2)(boost::python::object&, int) =  	&StackMobile::setTCPDatabaseAdaptor;
        void (StackMobile::*setUDPDatabaseAdaptorMobile1)(boost::python::object&) =       	&StackMobile::setUDPDatabaseAdaptor;
        void (StackMobile::*setUDPDatabaseAdaptorMobile2)(boost::python::object&, int) =	&StackMobile::setUDPDatabaseAdaptor;
	void (StackMobile::*releaseCacheMobile)(const std::string&) =				&StackMobile::releaseCache;
	void (StackMobile::*releaseCachesMobile)() =						&StackMobile::releaseCaches;
	boost::python::dict (StackMobile::*getCountersMobile)(const std::string&) =		&StackMobile::getCounters;
	boost::python::dict (StackMobile::*getCacheDataMobile)(const std::string&, const std::string&) =		&StackMobile::getCacheData;
	SharedPointer<Cache<StringCache>> (StackMobile::*getCacheByNameMobile)(const std::string&, const std::string&) =		&StackMobile::getCache;
        void (StackMobile::*setAnomalyCallbackMobile)(PyObject*, const std::string&) =		&StackMobile::setAnomalyCallback;
	void (StackMobile::*setOnFailCacheCallbackMobile)(const std::string&, PyObject*) = 	&StackMobile::setOnFailCacheCallback;
	const char* (StackMobile::*mobileName)() const = 					&StackMobile::name;

        boost::python::class_<StackMobile, bases<NetworkStack> >("StackMobile",
		"Class that implements a network stack for mobile enviroments")
		.def_readonly("name", mobileName,
			help_stack_name)
                .add_property("stats_level", &StackMobile::getStatisticsLevel, &StackMobile::setStatisticsLevel,
                        help_stack_stats_level)
                .add_property("flows_timeout", &StackMobile::getFlowsTimeout, &StackMobile::setFlowsTimeout,
                        help_stack_flows_timeout)
                .add_property("tcp_flows", &StackMobile::getTotalTCPFlows, &StackMobile::setTotalTCPFlows,
                        help_stack_tcp_flows)
                .add_property("udp_flows", &StackMobile::getTotalUDPFlows, &StackMobile::setTotalUDPFlows,
                        help_stack_udp_flows)
                .add_property("tcp_regex_manager", &StackMobile::getTCPRegexManager, &StackMobile::setTCPRegexManager,
                        help_stack_tcp_regex_manager)
                .add_property("udp_regex_manager", &StackMobile::getUDPRegexManager, &StackMobile::setUDPRegexManager,
                        help_stack_udp_regex_manager)
                .add_property("tcp_ip_set_manager", &StackMobile::getTCPIPSetManager, &StackMobile::setTCPIPSetManager,
                        help_stack_tcp_ip_set_manager)
                .add_property("udp_ip_set_manager", &StackMobile::getUDPIPSetManager, &StackMobile::setUDPIPSetManager,
                        help_stack_udp_ip_set_manager)
                .add_property("link_layer_tag", &StackMobile::getLinkLayerTag, &StackMobile::enableLinkLayerTagging,
                        help_stack_link_layer_tag)
		.add_property("tcp_flow_manager", make_function(&StackMobile::getTCPFlowManager, return_internal_reference<>()),
			help_stack_tcp_flow_manager)
		.add_property("udp_flow_manager", make_function(&StackMobile::getUDPFlowManager, return_internal_reference<>()),
			help_stack_udp_flow_manager)
		.add_property("mode", &StackMobile::getMode, &StackMobile::setMode,
			help_operation_mode)
		.def("increase_allocated_memory", increaseAllocatedMemoryMobile,
			help_increase_alloc_mem)
		.def("decrease_allocated_memory", decreaseAllocatedMemoryMobile,
			help_decrease_alloc_mem)
                .def("set_domain_name_manager", setDomainNameManagerMobile1,
			help_set_domain_name_manager)
                .def("set_domain_name_manager", setDomainNameManagerMobile2,
			help_set_domain_name_manager)
		.def("set_tcp_database_adaptor", setTCPDatabaseAdaptorMobile1,
			help_set_tcp_database_adaptor)
		.def("set_tcp_database_adaptor", setTCPDatabaseAdaptorMobile2,
			help_set_tcp_database_adaptor)
		.def("set_udp_database_adaptor", setUDPDatabaseAdaptorMobile1,
			help_set_udp_database_adaptor)
		.def("set_udp_database_adaptor", setUDPDatabaseAdaptorMobile2,
			help_set_udp_database_adaptor)
		.def("release_cache", releaseCacheMobile,
			help_release_cache)
		.def("release_caches", releaseCachesMobile,
			help_releases_caches)
		.def("get_counters", getCountersMobile,
			help_get_counters)
		.def("get_cache_data", getCacheDataMobile,
			help_stack_get_cache_data)
		.def("get_cache", getCacheByNameMobile,
			help_get_cache)
                .def("set_anomaly_callback", setAnomalyCallbackMobile,
			help_anomaly_callback)
                .def("set_on_fail_cache_callback", setOnFailCacheCallbackMobile,
			help_fail_cache_callback)
        ;

	// Definitions for the StackLanIPv6 class
	void (StackLanIPv6::*increaseAllocatedMemoryLan6)(const std::string&, int) =		&StackLanIPv6::increaseAllocatedMemory;
	void (StackLanIPv6::*decreaseAllocatedMemoryLan6)(const std::string&, int) =		&StackLanIPv6::decreaseAllocatedMemory;
        void (StackLanIPv6::*setDomainNameManagerLanIPv61)(const SharedPointer<DomainNameManager>&,const std::string&) = 	&StackLanIPv6::setDomainNameManager;
        void (StackLanIPv6::*setDomainNameManagerLanIPv62)(const SharedPointer<DomainNameManager>&,const std::string&, bool) = 	&StackLanIPv6::setDomainNameManager;
        void (StackLanIPv6::*setTCPDatabaseAdaptorLanIPv61)(boost::python::object&) = 		&StackLanIPv6::setTCPDatabaseAdaptor;
        void (StackLanIPv6::*setTCPDatabaseAdaptorLanIPv62)(boost::python::object&, int) =	&StackLanIPv6::setTCPDatabaseAdaptor;
        void (StackLanIPv6::*setUDPDatabaseAdaptorLanIPv61)(boost::python::object&) =     	&StackLanIPv6::setUDPDatabaseAdaptor;
        void (StackLanIPv6::*setUDPDatabaseAdaptorLanIPv62)(boost::python::object&, int) =	&StackLanIPv6::setUDPDatabaseAdaptor;
	void (StackLanIPv6::*releaseCacheLanIPv6)(const std::string&) =				&StackLanIPv6::releaseCache;
	void (StackLanIPv6::*releaseCachesLanIPv6)() =						&StackLanIPv6::releaseCaches;
	boost::python::dict (StackLanIPv6::*getCountersLanIPv6)(const std::string&) =		&StackLanIPv6::getCounters;
	boost::python::dict (StackLanIPv6::*getCacheDataLanIPv6)(const std::string&, const std::string&) =		&StackLanIPv6::getCacheData;
	SharedPointer<Cache<StringCache>> (StackLanIPv6::*getCacheByNameLanIPv6)(const std::string&, const std::string&) =		&StackLanIPv6::getCache;
        void (StackLanIPv6::*setAnomalyCallbackLanIPv6)(PyObject*, const std::string&) =	&StackLanIPv6::setAnomalyCallback;
	void (StackLanIPv6::*setOnFailCacheCallbackLanIPv6)(const std::string&, PyObject*) = 	&StackLanIPv6::setOnFailCacheCallback;
	const char* (StackLanIPv6::*lanIPv6Name)() const = 					&StackLanIPv6::name;

        boost::python::class_<StackLanIPv6, bases<NetworkStack> >("StackLanIPv6",
		"Class that implements a network stack for lan environments with IPv6")
		.def_readonly("name", lanIPv6Name, 
			help_stack_name)
                .add_property("stats_level", &StackLanIPv6::getStatisticsLevel, &StackLanIPv6::setStatisticsLevel,
                        help_stack_stats_level)
                .add_property("flows_timeout", &StackLanIPv6::getFlowsTimeout, &StackLanIPv6::setFlowsTimeout,
                        help_stack_flows_timeout)
                .add_property("tcp_flows", &StackLanIPv6::getTotalTCPFlows, &StackLanIPv6::setTotalTCPFlows,
                        help_stack_tcp_flows)
                .add_property("udp_flows", &StackLanIPv6::getTotalUDPFlows, &StackLanIPv6::setTotalUDPFlows,
                        help_stack_udp_flows)
                .add_property("tcp_regex_manager", &StackLanIPv6::getTCPRegexManager, &StackLanIPv6::setTCPRegexManager,
                        help_stack_tcp_regex_manager)
                .add_property("udp_regex_manager", &StackLanIPv6::getUDPRegexManager, &StackLanIPv6::setUDPRegexManager,
                        help_stack_udp_regex_manager)
                .add_property("tcp_ip_set_manager", &StackLanIPv6::getTCPIPSetManager, &StackLanIPv6::setTCPIPSetManager,
                        help_stack_tcp_ip_set_manager)
                .add_property("udp_ip_set_manager", &StackLanIPv6::getUDPIPSetManager, &StackLanIPv6::setUDPIPSetManager,
                        help_stack_udp_ip_set_manager)
                .add_property("link_layer_tag", &StackLanIPv6::getLinkLayerTag, &StackLanIPv6::enableLinkLayerTagging,
                        help_stack_link_layer_tag)
                .add_property("tcp_flow_manager", make_function(&StackLanIPv6::getTCPFlowManager, return_internal_reference<>()),
                        help_stack_tcp_flow_manager)
                .add_property("udp_flow_manager", make_function(&StackLanIPv6::getUDPFlowManager, return_internal_reference<>()),
                        help_stack_udp_flow_manager)
		.add_property("mode", &StackLanIPv6::getMode, &StackLanIPv6::setMode,
			help_operation_mode)
		.def("increase_allocated_memory", increaseAllocatedMemoryLan6,
			help_increase_alloc_mem)
		.def("decrease_allocated_memory", decreaseAllocatedMemoryLan6,
			help_decrease_alloc_mem)
                .def("set_domain_name_manager", setDomainNameManagerLanIPv61,
			help_set_domain_name_manager)
                .def("set_domain_name_manager", setDomainNameManagerLanIPv62,
			help_set_domain_name_manager)
                .def("set_tcp_database_adaptor", setTCPDatabaseAdaptorLanIPv61,
			help_set_tcp_database_adaptor)
                .def("set_tcp_database_adaptor", setTCPDatabaseAdaptorLanIPv62,
			help_set_tcp_database_adaptor)
                .def("set_udp_database_adaptor", setUDPDatabaseAdaptorLanIPv61,
			help_set_udp_database_adaptor)
                .def("set_udp_database_adaptor", setUDPDatabaseAdaptorLanIPv62,
			help_set_udp_database_adaptor)
		.def("release_cache", releaseCacheLanIPv6,
			help_release_cache)
		.def("release_caches", releaseCachesLanIPv6,
			help_releases_caches)
		.def("get_counters", getCountersLanIPv6,
			help_get_counters)
		.def("get_cache_data", getCacheDataLanIPv6,
			help_stack_get_cache_data)
		.def("get_cache", getCacheByNameLanIPv6,
			help_get_cache)
                .def("set_anomaly_callback", setAnomalyCallbackLanIPv6,
			help_anomaly_callback)
                .def("set_on_fail_cache_callback", setOnFailCacheCallbackLanIPv6,
			help_fail_cache_callback)
	;

        // Definitions for the StackVirtual class
	void (StackVirtual::*increaseAllocatedMemoryVirt)(const std::string&, int) =	&StackVirtual::increaseAllocatedMemory;
	void (StackVirtual::*decreaseAllocatedMemoryVirt)(const std::string&, int) =	&StackVirtual::decreaseAllocatedMemory;
        void (StackVirtual::*setDomainNameManagerVirt1)(const SharedPointer<DomainNameManager>&, const std::string&) =           &StackVirtual::setDomainNameManager;
        void (StackVirtual::*setDomainNameManagerVirt2)(const SharedPointer<DomainNameManager>&, const std::string&, bool) =     &StackVirtual::setDomainNameManager;
        void (StackVirtual::*setTCPDatabaseAdaptorVirt1)(boost::python::object&) =            	&StackVirtual::setTCPDatabaseAdaptor;
        void (StackVirtual::*setTCPDatabaseAdaptorVirt2)(boost::python::object&, int) =       	&StackVirtual::setTCPDatabaseAdaptor;
        void (StackVirtual::*setUDPDatabaseAdaptorVirt1)(boost::python::object&) =            	&StackVirtual::setUDPDatabaseAdaptor;
        void (StackVirtual::*setUDPDatabaseAdaptorVirt2)(boost::python::object&, int) =       	&StackVirtual::setUDPDatabaseAdaptor;
	void (StackVirtual::*releaseCacheVirtual)(const std::string&) =				&StackVirtual::releaseCache;
	void (StackVirtual::*releaseCachesVirtual)() =						&StackVirtual::releaseCaches;
	boost::python::dict (StackVirtual::*getCountersVirtual)(const std::string&) =		&StackVirtual::getCounters;
	boost::python::dict (StackVirtual::*getCacheDataVirtual)(const std::string&, const std::string&) =		&StackVirtual::getCacheData;
	SharedPointer<Cache<StringCache>> (StackVirtual::*getCacheByNameVirtual)(const std::string&, const std::string&) =		&StackVirtual::getCache;
        void (StackVirtual::*setAnomalyCallbackVirtual)(PyObject*, const std::string&) =	&StackVirtual::setAnomalyCallback;
	void (StackVirtual::*setOnFailCacheCallbackVirtual)(const std::string&, PyObject*) = 	&StackVirtual::setOnFailCacheCallback;
	const char* (StackVirtual::*virtualName)() const = 					&StackVirtual::name;

        boost::python::class_<StackVirtual, bases<NetworkStack> >("StackVirtual",
                "Class that implements a network stack for cloud/virtual environments")
                .def_readonly("name", virtualName,
			help_stack_name)
                .add_property("stats_level", &StackVirtual::getStatisticsLevel, &StackVirtual::setStatisticsLevel,
                        help_stack_stats_level)
                .add_property("flows_timeout", &StackVirtual::getFlowsTimeout, &StackVirtual::setFlowsTimeout,
                        help_stack_flows_timeout)
                .add_property("tcp_flows", &StackVirtual::getTotalTCPFlows, &StackVirtual::setTotalTCPFlows,
                        help_stack_tcp_flows)
                .add_property("udp_flows", &StackVirtual::getTotalUDPFlows, &StackVirtual::setTotalUDPFlows,
                        help_stack_udp_flows)
                .add_property("tcp_regex_manager", &StackVirtual::getTCPRegexManager, &StackVirtual::setTCPRegexManager,
                        help_stack_tcp_regex_manager)
                .add_property("udp_regex_manager", &StackVirtual::getUDPRegexManager, &StackVirtual::setUDPRegexManager,
                        help_stack_udp_regex_manager)
                .add_property("tcp_ip_set_manager", &StackVirtual::getTCPIPSetManager, &StackVirtual::setTCPIPSetManager,
                        help_stack_tcp_ip_set_manager)
                .add_property("udp_ip_set_manager", &StackVirtual::getUDPIPSetManager, &StackVirtual::setUDPIPSetManager,
                        help_stack_udp_ip_set_manager)
                .add_property("link_layer_tag", &StackVirtual::getLinkLayerTag, &StackVirtual::enableLinkLayerTagging,
                        help_stack_link_layer_tag)
                .add_property("tcp_flow_manager", make_function(&StackVirtual::getTCPFlowManager, return_internal_reference<>()),
                        help_stack_tcp_flow_manager)
                .add_property("udp_flow_manager", make_function(&StackVirtual::getUDPFlowManager, return_internal_reference<>()),
                        help_stack_udp_flow_manager)
		.add_property("mode", &StackVirtual::getMode, &StackVirtual::setMode,
			help_operation_mode)
		.def("increase_allocated_memory", increaseAllocatedMemoryVirt,
			help_increase_alloc_mem)
		.def("decrease_allocated_memory", decreaseAllocatedMemoryVirt,
			help_decrease_alloc_mem)
                .def("set_domain_name_manager", setDomainNameManagerVirt1,
			help_set_domain_name_manager)
                .def("set_domain_name_manager", setDomainNameManagerVirt2,
			help_set_domain_name_manager)
                .def("set_tcp_database_adaptor", setTCPDatabaseAdaptorVirt1,
			help_set_tcp_database_adaptor)
                .def("set_tcp_database_adaptor", setTCPDatabaseAdaptorVirt2,
			help_set_tcp_database_adaptor)
                .def("set_udp_database_adaptor", setUDPDatabaseAdaptorVirt1,
			help_set_udp_database_adaptor)
                .def("set_udp_database_adaptor", setUDPDatabaseAdaptorVirt2,
			help_set_udp_database_adaptor)
		.def("release_cache", releaseCacheVirtual,
			help_release_cache)
		.def("release_caches", releaseCachesVirtual,
			help_releases_caches)
		.def("get_counters", getCountersVirtual,
			help_get_counters)
		.def("get_cache_data", getCacheDataVirtual,
			help_stack_get_cache_data)
		.def("get_cache", getCacheByNameVirtual,
			help_get_cache)
                .def("set_anomaly_callback", setAnomalyCallbackVirtual,
			help_anomaly_callback)
                .def("set_on_fail_cache_callback", setOnFailCacheCallbackVirtual,
			help_fail_cache_callback)
        ;

        // Definitions for the StackOpenFlow class
	void (StackOpenFlow::*increaseAllocatedMemoryOF)(const std::string&, int) =		&StackOpenFlow::increaseAllocatedMemory;
	void (StackOpenFlow::*decreaseAllocatedMemoryOF)(const std::string&, int) =		&StackOpenFlow::decreaseAllocatedMemory;
        void (StackOpenFlow::*setDomainNameManagerOF1)(const SharedPointer<DomainNameManager>&, const std::string&) =    	&StackOpenFlow::setDomainNameManager;
        void (StackOpenFlow::*setDomainNameManagerOF2)(const SharedPointer<DomainNameManager>&, const std::string&, bool) =    	&StackOpenFlow::setDomainNameManager;
        void (StackOpenFlow::*setTCPDatabaseAdaptorOF1)(boost::python::object&) =              	&StackOpenFlow::setTCPDatabaseAdaptor;
        void (StackOpenFlow::*setTCPDatabaseAdaptorOF2)(boost::python::object&, int) =         	&StackOpenFlow::setTCPDatabaseAdaptor;
        void (StackOpenFlow::*setUDPDatabaseAdaptorOF1)(boost::python::object&) =              	&StackOpenFlow::setUDPDatabaseAdaptor;
        void (StackOpenFlow::*setUDPDatabaseAdaptorOF2)(boost::python::object&, int) =         	&StackOpenFlow::setUDPDatabaseAdaptor;
        void (StackOpenFlow::*releaseCacheOpenFlow)(const std::string&) =                  	&StackOpenFlow::releaseCache;
        void (StackOpenFlow::*releaseCachesOpenFlow)() =                          		&StackOpenFlow::releaseCaches;
	boost::python::dict (StackOpenFlow::*getCountersOpenFlow)(const std::string&) =		&StackOpenFlow::getCounters;
	boost::python::dict (StackOpenFlow::*getCacheDataOpenFlow)(const std::string&, const std::string&) =		&StackOpenFlow::getCacheData;
	SharedPointer<Cache<StringCache>> (StackOpenFlow::*getCacheByNameOF)(const std::string&, const std::string&) =		&StackOpenFlow::getCache;
        void (StackOpenFlow::*setAnomalyCallbackOpenFlow)(PyObject*, const std::string&) =	&StackOpenFlow::setAnomalyCallback;
	void (StackOpenFlow::*setOnFailCacheCallbackOpenFlow)(const std::string&, PyObject*) = 	&StackOpenFlow::setOnFailCacheCallback;
	const char* (StackOpenFlow::*openflowName)() const = 					&StackOpenFlow::name;

        boost::python::class_<StackOpenFlow, bases<NetworkStack> >("StackOpenFlow",
                "Class that implements a network stack for openflow environments")
                .def_readonly("name", openflowName,
			help_stack_name)
                .add_property("stats_level", &StackOpenFlow::getStatisticsLevel, &StackOpenFlow::setStatisticsLevel,
                        help_stack_stats_level)
                .add_property("flows_timeout", &StackOpenFlow::getFlowsTimeout, &StackOpenFlow::setFlowsTimeout,
                        help_stack_flows_timeout)
                .add_property("tcp_flows", &StackOpenFlow::getTotalTCPFlows, &StackOpenFlow::setTotalTCPFlows,
                        help_stack_tcp_flows)
                .add_property("udp_flows", &StackOpenFlow::getTotalUDPFlows, &StackOpenFlow::setTotalUDPFlows,
                        help_stack_udp_flows)
                .add_property("tcp_regex_manager", &StackOpenFlow::getTCPRegexManager, &StackOpenFlow::setTCPRegexManager,
                        help_stack_tcp_regex_manager)
                .add_property("udp_regex_manager", &StackOpenFlow::getUDPRegexManager, &StackOpenFlow::setUDPRegexManager,
                        help_stack_udp_regex_manager)
                .add_property("tcp_ip_set_manager", &StackOpenFlow::getTCPIPSetManager, &StackOpenFlow::setTCPIPSetManager,
                        help_stack_tcp_ip_set_manager)
                .add_property("udp_ip_set_manager", &StackOpenFlow::getUDPIPSetManager, &StackOpenFlow::setUDPIPSetManager,
                        help_stack_udp_ip_set_manager)
                .add_property("link_layer_tag", &StackOpenFlow::getLinkLayerTag, &StackOpenFlow::enableLinkLayerTagging,
                        help_stack_link_layer_tag)
                .add_property("tcp_flow_manager", make_function(&StackOpenFlow::getTCPFlowManager, return_internal_reference<>()),
                        help_stack_tcp_flow_manager)
                .add_property("udp_flow_manager", make_function(&StackOpenFlow::getUDPFlowManager, return_internal_reference<>()),
                        help_stack_udp_flow_manager)
		.add_property("mode", &StackOpenFlow::getMode, &StackOpenFlow::setMode,
			help_operation_mode)
		.def("increase_allocated_memory", increaseAllocatedMemoryOF,
			help_increase_alloc_mem)
		.def("decrease_allocated_memory", decreaseAllocatedMemoryOF,
			help_decrease_alloc_mem)
                .def("set_domain_name_manager", setDomainNameManagerOF1,
			help_set_domain_name_manager)
                .def("set_domain_name_manager", setDomainNameManagerOF2,
			help_set_domain_name_manager)
                .def("set_tcp_database_adaptor", setTCPDatabaseAdaptorOF1,
			help_set_tcp_database_adaptor)
                .def("set_tcp_database_adaptor", setTCPDatabaseAdaptorOF2,
			help_set_tcp_database_adaptor)
                .def("set_udp_database_adaptor", setUDPDatabaseAdaptorOF1,
			help_set_udp_database_adaptor)
                .def("set_udp_database_adaptor", setUDPDatabaseAdaptorOF2,
			help_set_udp_database_adaptor)
                .def("release_cache", releaseCacheOpenFlow,
			help_release_cache)
                .def("release_caches", releaseCachesOpenFlow,
			help_releases_caches)
                .def("get_counters", getCountersOpenFlow,
			help_get_counters)
                .def("get_cache_data", getCacheDataOpenFlow,
			help_stack_get_cache_data)
                .def("get_cache", getCacheByNameOF,
			help_get_cache)
                .def("set_anomaly_callback", setAnomalyCallbackOpenFlow,
			help_anomaly_callback)
                .def("set_on_fail_cache_callback", setOnFailCacheCallbackOpenFlow,
			help_fail_cache_callback)
	;

        // Definitions for the StackMobileIPv6 class
        void (StackMobileIPv6::*increaseAllocatedMemoryMobile6)(const std::string&, int) =	    &StackMobileIPv6::increaseAllocatedMemory;
        void (StackMobileIPv6::*decreaseAllocatedMemoryMobile6)(const std::string&, int) =          &StackMobileIPv6::decreaseAllocatedMemory;
        void (StackMobileIPv6::*setDomainNameManagerMobile6_1)(const SharedPointer<DomainNameManager>&, const std::string&) =         &StackMobileIPv6::setDomainNameManager;
        void (StackMobileIPv6::*setDomainNameManagerMobile6_2)(const SharedPointer<DomainNameManager>&, const std::string&, bool) =   &StackMobileIPv6::setDomainNameManager;
        void (StackMobileIPv6::*setTCPDatabaseAdaptorMobile6_1)(boost::python::object&) =           &StackMobileIPv6::setTCPDatabaseAdaptor;
        void (StackMobileIPv6::*setTCPDatabaseAdaptorMobile6_2)(boost::python::object&, int) =      &StackMobileIPv6::setTCPDatabaseAdaptor;
        void (StackMobileIPv6::*setUDPDatabaseAdaptorMobile6_1)(boost::python::object&) =           &StackMobileIPv6::setUDPDatabaseAdaptor;
        void (StackMobileIPv6::*setUDPDatabaseAdaptorMobile6_2)(boost::python::object&, int) =      &StackMobileIPv6::setUDPDatabaseAdaptor;
        void (StackMobileIPv6::*releaseCacheMobile6)(const std::string&) =                          &StackMobileIPv6::releaseCache;
        void (StackMobileIPv6::*releaseCachesMobile6)() =                                           &StackMobileIPv6::releaseCaches;
        boost::python::dict (StackMobileIPv6::*getCountersMobile6)(const std::string&) =            &StackMobileIPv6::getCounters;
        boost::python::dict (StackMobileIPv6::*getCacheDataMobile6)(const std::string&, const std::string&) =               &StackMobileIPv6::getCacheData;
	SharedPointer<Cache<StringCache>> (StackMobileIPv6::*getCacheByNameMobile6)(const std::string&, const std::string&) =		&StackMobileIPv6::getCache;
        void (StackMobileIPv6::*setAnomalyCallbackMobile6)(PyObject*, const std::string&) =         &StackMobileIPv6::setAnomalyCallback;
	void (StackMobileIPv6::*setOnFailCacheCallbackMobile6)(const std::string&, PyObject*) =     &StackMobileIPv6::setOnFailCacheCallback;
	const char* (StackMobileIPv6::*mobileIPv6Name)() const = 			            &StackMobileIPv6::name;

        boost::python::class_<StackMobileIPv6, bases<NetworkStack> >("StackMobileIPv6",
                "Class that implements a network stack for IPv6 mobile enviroments")
                .def_readonly("name", mobileIPv6Name,
                        help_stack_name)
                .add_property("stats_level", &StackMobileIPv6::getStatisticsLevel, &StackMobileIPv6::setStatisticsLevel,
                        help_stack_stats_level)
                .add_property("flows_timeout", &StackMobileIPv6::getFlowsTimeout, &StackMobileIPv6::setFlowsTimeout,
                        help_stack_flows_timeout)
                .add_property("tcp_flows", &StackMobileIPv6::getTotalTCPFlows, &StackMobileIPv6::setTotalTCPFlows,
                        help_stack_tcp_flows)
                .add_property("udp_flows", &StackMobileIPv6::getTotalUDPFlows, &StackMobileIPv6::setTotalUDPFlows,
                        help_stack_udp_flows)
                .add_property("tcp_regex_manager", &StackMobileIPv6::getTCPRegexManager, &StackMobileIPv6::setTCPRegexManager,
                        help_stack_tcp_regex_manager)
                .add_property("udp_regex_manager", &StackMobileIPv6::getUDPRegexManager, &StackMobileIPv6::setUDPRegexManager,
                        help_stack_udp_regex_manager)
                .add_property("tcp_ip_set_manager", &StackMobileIPv6::getTCPIPSetManager, &StackMobileIPv6::setTCPIPSetManager,
                        help_stack_tcp_ip_set_manager)
                .add_property("udp_ip_set_manager", &StackMobileIPv6::getUDPIPSetManager, &StackMobileIPv6::setUDPIPSetManager,
                        help_stack_udp_ip_set_manager)
                .add_property("link_layer_tag", &StackMobileIPv6::getLinkLayerTag, &StackMobileIPv6::enableLinkLayerTagging,
                        help_stack_link_layer_tag)
                .add_property("tcp_flow_manager", make_function(&StackMobileIPv6::getTCPFlowManager, return_internal_reference<>()),
                        help_stack_tcp_flow_manager)
                .add_property("udp_flow_manager", make_function(&StackMobileIPv6::getUDPFlowManager, return_internal_reference<>()),
                        help_stack_udp_flow_manager)
		.add_property("mode", &StackMobileIPv6::getMode, &StackMobileIPv6::setMode,
			help_operation_mode)
                .def("increase_allocated_memory", increaseAllocatedMemoryMobile6,
                        help_increase_alloc_mem)
                .def("decrease_allocated_memory", decreaseAllocatedMemoryMobile6,
                        help_decrease_alloc_mem)
                .def("set_domain_name_manager", setDomainNameManagerMobile6_1,
                        help_set_domain_name_manager)
                .def("set_domain_name_manager", setDomainNameManagerMobile6_2,
                        help_set_domain_name_manager)
                .def("set_tcp_database_adaptor", setTCPDatabaseAdaptorMobile6_1,
                        help_set_tcp_database_adaptor)
                .def("set_tcp_database_adaptor", setTCPDatabaseAdaptorMobile6_2,
                        help_set_tcp_database_adaptor)
                .def("set_udp_database_adaptor", setUDPDatabaseAdaptorMobile6_1,
                        help_set_udp_database_adaptor)
                .def("set_udp_database_adaptor", setUDPDatabaseAdaptorMobile6_2,
                        help_set_udp_database_adaptor)
                .def("release_cache", releaseCacheMobile6,
                        help_release_cache)
                .def("release_caches", releaseCachesMobile6,
                        help_releases_caches)
                .def("get_counters", getCountersMobile6,
                        help_get_counters)
                .def("get_cache_data", getCacheDataMobile6,
                        help_stack_get_cache_data)
                .def("get_cache", getCacheByNameMobile6,
                        help_get_cache)
                .def("set_anomaly_callback", setAnomalyCallbackMobile6,
                        help_anomaly_callback)
                .def("set_on_fail_cache_callback", setOnFailCacheCallbackMobile6,
			help_fail_cache_callback)
        ;
	
	boost::python::class_<Regex, SharedPointer<Regex>, boost::noncopyable>("Regex",
                "This class contains the functionality for manage regular expressions as well as how to connect the object with others.",
		init<const std::string&, const std::string&>())
		.def(init<const std::string&, const std::string&, boost::python::object>())
		.def(init<const std::string&, const std::string&, boost::python::object, const SharedPointer<Regex>&>())
		.def_readonly("expression", &Regex::getExpression,
			help_regex_expression)
		.def_readonly("name", &Regex::name,
			help_regex_name) 
		.def_readonly("matchs", &Regex::getMatchs,
			help_regex_matchs)
		.add_property("callback", &Regex::getCallback, &Regex::setCallback,
			help_regex_callback)
		.add_property("next_regex",&Regex::getNextRegex, &Regex::setNextRegex,
			help_regex_next_regex)
		.add_property("next_regex_manager",&Regex::getNextRegexManager, &Regex::setNextRegexManager,
			help_regex_next_regex_manager)
		.add_property("write_packet",&Regex::getWritePacket, &Regex::setWritePacket,
			help_regex_write_packet)
		.def(self_ns::str(self_ns::self))
	;

	// for overload the methods within the class
	void (PacketDispatcher::*setStackPtr)(const boost::python::object&) = 	&PacketDispatcher::setStack;
	void (PacketDispatcher::*showCurrentPayloadPacketPdis)() const =		&PacketDispatcher::showCurrentPayloadPacket;
	void (PacketDispatcher::*showPdisStatistics)() =			&PacketDispatcher::statistics;
	void (PacketDispatcher::*open1)(const std::string&) =			&PacketDispatcher::open;
	void (PacketDispatcher::*open2)(const std::string&, int) =		&PacketDispatcher::open;

	boost::python::class_<PacketDispatcher, boost::noncopyable>("PacketDispatcher",
		"Class that manage the packets and forwards to the associated network stack")
		.def(init<>())	// Default constructor
                .def(init<const std::string&>()) // Constructor for using with the 'with' statement
                .def(init<const std::string&, int>()) // Constructor for using with the 'with' statement
		.def_readonly("status", &PacketDispatcher::getStatus,
			help_pdis_status)
		.def_readonly("packets", &PacketDispatcher::getTotalPackets,
			help_pdis_packets)
		.def_readonly("received_packets", &PacketDispatcher::getTotalReceivedPackets,
			help_pdis_received_packets)
		.def_readonly("dropped_packets", &PacketDispatcher::getTotalDroppedPackets,
			help_pdis_dropped_packets)
		.def_readonly("ifdropped_packets", &PacketDispatcher::getTotalIfDroppedPackets,
			help_pdis_ifdropped_packets)
		.def_readonly("bytes", &PacketDispatcher::getTotalBytes,
			help_pdis_bytes)
		.def_readonly("is_packet_accepted", &PacketDispatcher::isPacketAccepted,
			help_pdis_is_packet_accepted)
		.def_readonly("pcap_files_duration", &PacketDispatcher::getPcapFilesDuration,
			help_pdis_pcap_files_duration)
		.def_readonly("device_status", &PacketDispatcher::getNetworkDeviceStatus,
			help_pdis_device_status)
		.add_property("pcap_buffer_size", &PacketDispatcher::getPcapBufferSize, &PacketDispatcher::setPcapBufferSize,
			help_pdis_pcap_buffer_size)
		.add_property("stack", &PacketDispatcher::getStack, setStackPtr,
			help_pdis_stack)
		.add_property("enable_shell", &PacketDispatcher::getShell, &PacketDispatcher::setShell,
			help_pdis_enable_shell)
		.add_property("pcap_filter", &PacketDispatcher::getPcapFilter, &PacketDispatcher::setPcapFilter,
			help_pdis_pcap_filter)
		.add_property("evidences", &PacketDispatcher::getEvidences, &PacketDispatcher::setEvidences,
			help_pdis_evidences)
		.add_property("log_user_commands", &PacketDispatcher::getLogUserCommands, &PacketDispatcher::setLogUserCommands,
			help_pdis_log_user_commands)
		.add_property("http_port", &PacketDispatcher::getHTTPPort, &PacketDispatcher::setHTTPPort,
			help_pdis_http_port)
		.add_property("http_address", &PacketDispatcher::getHTTPIPAddress, &PacketDispatcher::setHTTPIPAddress,
			help_pdis_http_address)
		.add_property("authorized_ip_address", &PacketDispatcher::getAuthorizedIPAddresses, &PacketDispatcher::addAuthorizedIPAddresses,
			help_pdis_authorized_ip_address)
		.add_property("network_device_change_callback", &PacketDispatcher::getNetworkDeviceStatusCallback, &PacketDispatcher::setNetworkDeviceStatusCallback,
			help_pdis_net_callback)
		.add_property("authorization_code_token", &PacketDispatcher::getAuthorizationCodeToken, &PacketDispatcher::setAuthorizationCodeToken,
			help_pdis_auth_code_token)
		.add_property("alarm_callback", &PacketDispatcher::getPythonAlarmCallback, &PacketDispatcher::setAlarmCallback,
			help_pdis_alarm_callback)
		.add_property("log_rest_api_code", &PacketDispatcher::getLogRestApiPythonCode, &PacketDispatcher::setLogRestApiPythonCode,
			help_pdis_log_rest_code)
		.def("open", open1,
			help_pdis_open)
		.def("open", open2,
			help_pdis_open)
		.def("close", &PacketDispatcher::close,
			help_pdis_close)
		.def("run", &PacketDispatcher::run,
			help_pdis_run)
		.def("forward_packet", &PacketDispatcher::forwardPacket,
			help_pdis_forward_packet)
		.def("add_timer", &PacketDispatcher::addTimer,
			help_pdis_add_timer)
		.def("remove_timer", &PacketDispatcher::removeTimer,
			help_pdis_remove_timer)
		.def("show_current_packet", showCurrentPayloadPacketPdis,
			help_pdis_show_packet)
		.def("show", showPdisStatistics,
			help_pdis_show)
		.def("show_system", &PacketDispatcher::showSystemProcessInformation,
			help_pdis_show_process_system)
		.def("__enter__", &PacketDispatcher::__enter__, return_value_policy<reference_existing_object>())
		.def("__exit__", &PacketDispatcher::__exit__)
	;

	void (RegexManager::*addRegex1)(const std::string&, const std::string&) = &RegexManager::addRegex;
	void (RegexManager::*addRegex2)(const SharedPointer<Regex>&) = &RegexManager::addRegex;
	void (RegexManager::*removeRegex1)(const std::string&, const std::string&) = &RegexManager::removeRegex;
	void (RegexManager::*removeRegex2)(const SharedPointer<Regex>&) = &RegexManager::removeRegex;
        void (RegexManager::*showRegexs)() const			= &RegexManager::statistics;
        void (RegexManager::*showRegexByName)(const std::string&) const	= &RegexManager::statistics;
        void (RegexManager::*showMatchedRegexs)() const			= &RegexManager::showMatchedRegexs;
        void (RegexManager::*setRegexManagerName)(const std::string&)	= &RegexManager::name;
	const char* (RegexManager::*getRegexManagerName)() const 	= &RegexManager::name;

	boost::python::class_<RegexManager, SharedPointer<RegexManager>, boost::noncopyable >("RegexManager",
		"This class contains Regex objects and how are they manage.")
		.def(init<>())
		.def(init<const std::string&>())
		.def(init<boost::python::list&>())
		.def(init<const std::string&, boost::python::list&>())
		.def("__iter__", boost::python::range(&RegexManager::begin, &RegexManager::end),
			help_regex_manager_iter)
		.add_property("name", getRegexManagerName, setRegexManagerName,
			help_regex_manager_name)
                .add_property("callback", &RegexManager::getCallback, &RegexManager::setCallback,
                        help_regex_manager_callback)
		.def("add_regex", addRegex1,
			help_regex_manager_add_regex)
		.def("add_regex", addRegex2,
			help_regex_manager_add_regex)
		.def("remove_regex", removeRegex1,
			help_regex_manager_remove_regex)
		.def("remove_regex", removeRegex2,
			help_regex_manager_remove_regex)
		.def("__len__", &RegexManager::getTotalRegexs,
			help_regex_manager_len)
		.def("show", showRegexs,
			help_regex_manager_show)
		.def("show", showRegexByName,
			help_regex_manager_show_name)
		.def("show_matched_regexs", showMatchedRegexs,
			help_regex_manager_show_matchs)
		.def("reset", &RegexManager::resetStatistics,
			help_regex_manager_reset)
	;

        void (FlowManager::*showStats)() const				= &FlowManager::statistics;
        void (FlowManager::*showFlows)() const				= &FlowManager::showFlows;
        void (FlowManager::*showFlows2)(int) const				= &FlowManager::showFlows;
        void (FlowManager::*showFlowsByProtocol)(const std::string&) const	= &FlowManager::showFlows;
        void (FlowManager::*showFlowsByProtocol2)(const std::string&, int) const	= &FlowManager::showFlows;
	void (FlowManager::*flushAll)()					= &FlowManager::flush;
	void (FlowManager::*flushByProto)(const std::string&) 		= &FlowManager::flush;
	void (FlowManager::*purgeAll)()					= &FlowManager::purge;

	boost::python::class_<FlowManager, SharedPointer<FlowManager>, boost::noncopyable >("FlowManager",
		"This class stores in memory the active Flows.")
		.def("__iter__", boost::python::range<return_value_policy<copy_non_const_reference> >(
			&FlowManager::begin, &FlowManager::end),
			help_flow_manager_iter)
		.def("__len__", &FlowManager::getTotalFlows,
			help_flow_manager_len)
		.def_readonly("flows", &FlowManager::getTotalFlows,
			help_flow_manager_len)
		.def_readonly("process_flows", &FlowManager::getTotalProcessFlows,
			help_flow_manager_process_flows)
		.def_readonly("timeout_flows", &FlowManager::getTotalTimeoutFlows, 
			help_flow_manager_timeout_flows)
		.add_property("timeout", &FlowManager::getTimeout, &FlowManager::setTimeout, 
			help_flow_manager_timeout)
		.def("show", showStats,
			help_flow_manager_stats)
		.def("show_flows", showFlows2,
			help_flow_manager_show_flows)
		.def("show_flows", showFlowsByProtocol2,
			help_flow_manager_show_flows_pr)
		.def("show_flows", showFlows,
			help_flow_manager_show_flows)
		.def("show_flows", showFlowsByProtocol,
			help_flow_manager_show_flows_pr)
		.def("flush", flushAll,
			help_flow_manager_flush) 
		.def("flush", flushByProto,
			help_flow_manager_flush) 
		.def("purge", purgeAll,
			help_flow_manager_purge) 
	;
	
	boost::python::class_<Flow, SharedPointer<Flow>>("Flow",
		"Class that keeps all the relevant information of a network flow.")
		.def_readonly("direction", &Flow::getDirection,
			help_flow_direction)
		.def_readonly("protocol", &Flow::getProtocol,
			help_flow_protocol)
		.def_readonly("dst_port", &Flow::getDestinationPort,
			help_flow_dst_port)
		.def_readonly("src_port", &Flow::getSourcePort,
			help_flow_src_port)
		.def_readonly("dst_ip", &Flow::getDstAddrDotNotation,
			help_flow_dst_ip)
		.def_readonly("src_ip", &Flow::getSrcAddrDotNotation,
			help_flow_src_ip)
		.def_readonly("packets_layer7", &Flow::getTotalPacketsLayer7,
			help_flow_packets_layer7)
		.def_readonly("packets", &Flow::getTotalPackets,
			help_flow_packets)
		.def_readonly("upstream_packets", &Flow::getTotalUpstreamPackets,
			help_flow_up_packets)
		.def_readonly("downstream_packets", &Flow::getTotalDownstreamPackets,
			help_flow_down_packets)
		.def_readonly("bytes", &Flow::getTotalBytes,
			help_flow_bytes)
		.def_readonly("upstream_bytes", &Flow::getTotalUpstreamBytes,
			help_flow_up_bytes)
		.def_readonly("downstream_bytes", &Flow::getTotalDownstreamBytes,
			help_flow_down_bytes)
		.def_readonly("have_tag", &Flow::haveTag,
			help_flow_have_tag)
		.add_property("reject",  &Flow::isReject, &Flow::setReject,
                        help_flow_reject)
		.def_readonly("tag", &Flow::getTag,
			help_flow_tag)
		.add_property("evidence", &Flow::haveEvidence, &Flow::setEvidence,
			help_flow_evidence)
		.add_property("accept", &Flow::isAccept, &Flow::setAccept,
			help_flow_accept)
		.add_property("alerted", &Flow::isAlerted, &Flow::setAlerted,
			help_flow_alerted)
		.add_property("label", &Flow::getLabel, &Flow::setLabel,
			help_flow_label)
		.def_readonly("duration", &Flow::getDuration,
			help_flow_duration)
		.def_readonly("upstream_ttl", &Flow::getUpstreamTTL,
			help_flow_upstream_ttl)
		.def_readonly("downstream_ttl", &Flow::getDownstreamTTL,
			help_flow_downstream_ttl)
		.add_property("ip_set", make_function(&Flow::getIPSetInfo, return_internal_reference<>()),
			help_flow_ip_set)
		.add_property("tcp_info", make_function(&Flow::getTCPInfoObject, return_internal_reference<>()),
			help_flow_tcp_info)
		.add_property("http_info", make_function(&Flow::getHTTPInfoObject, return_internal_reference<>()),
			help_flow_http_info)
		.add_property("sip_info", make_function(&Flow::getSIPInfoObject, return_internal_reference<>()),
			help_flow_sip_info)
		.add_property("smtp_info", make_function(&Flow::getSMTPInfoObject, return_internal_reference<>()),
			help_flow_smtp_info)
		.add_property("pop_info", make_function(&Flow::getPOPInfoObject, return_internal_reference<>()),
			help_flow_pop_info)
		.add_property("imap_info", make_function(&Flow::getIMAPInfoObject, return_internal_reference<>()),
			help_flow_imap_info)
		.add_property("frequencies", make_function(&Flow::getFrequencies, return_internal_reference<>()),
			help_flow_frequencies)
		.add_property("packet_frequencies", make_function(&Flow::getPacketFrequencies, return_internal_reference<>()),
			help_flow_packet_frequencies)
		.add_property("dns_info", make_function(&Flow::getDNSInfoObject, return_internal_reference<>()),
			help_flow_dns_info)
		.add_property("ssl_info", make_function(&Flow::getSSLInfoObject, return_internal_reference<>()),
			help_flow_ssl_info)
		.add_property("ssdp_info", make_function(&Flow::getSSDPInfoObject, return_internal_reference<>()),
			help_flow_ssdp_info)
		.add_property("bitcoin_info", make_function(&Flow::getBitcoinInfoObject, return_internal_reference<>()),
			help_flow_bitcoin_info)
		.add_property("coap_info", make_function(&Flow::getCoAPInfoObject, return_internal_reference<>()),
			help_flow_coap_info)
		.add_property("mqtt_info", make_function(&Flow::getMQTTInfoObject, return_internal_reference<>()),
			help_flow_mqtt_info)
		.add_property("netbios_info", make_function(&Flow::getNetbiosInfoObject, return_internal_reference<>()),
			help_flow_netbios_info)
		.add_property("dhcp_info", make_function(&Flow::getDHCPInfoObject, return_internal_reference<>()),
			help_flow_dhcp_info)
		.add_property("smb_info", make_function(&Flow::getSMBInfoObject, return_internal_reference<>()),
			help_flow_smb_info)
		.add_property("dhcp6_info", make_function(&Flow::getDHCPv6InfoObject, return_internal_reference<>()),
			help_flow_dhcp6_info)
		.add_property("ssh_info", make_function(&Flow::getSSHInfoObject, return_internal_reference<>()),
			help_flow_ssh_info)
		.add_property("dcerpc_info", make_function(&Flow::getDCERPCInfoObject, return_internal_reference<>()),
			help_flow_dcerpc_info)
		.add_property("quic_info", make_function(&Flow::getQuicInfoObject, return_internal_reference<>()),
			help_flow_quic_info)
		.add_property("dtls_info", make_function(&Flow::getDTLSInfoObject, return_internal_reference<>()),
			help_flow_dtls_info)
		.add_property("regex", make_function(&Flow::getRegex, return_internal_reference<>()),
			help_flow_regex)
		.add_property("regex_manager", make_function(&Flow::getRegexManager, return_internal_reference<>()), &Flow::setRegexManager, 
			help_flow_regex_manager)
		.def_readonly("payload", &Flow::getPayload,
			help_flow_payload)
		.add_property("anomaly", make_function(&Flow::getFlowAnomalyString, return_value_policy<return_by_value>()),
			help_flow_anomaly)
		.add_property("l7protocol", make_function(&Flow::getL7ProtocolName, return_value_policy<return_by_value>()),
			help_flow_l7_protocol_name)
		.def("detach", &Flow::detach,
			help_flow_detach) 
		.def(self_ns::str(self_ns::self))
	;
        
	boost::python::class_<DTLSInfo, SharedPointer<DTLSInfo>, boost::noncopyable>("DTLSInfo",
		"Class that stores information of DTLS.")
                .def_readonly("pdus", &DTLSInfo::getTotalDataPdus,
                        help_dtls_pdus)
                .def_readonly("version", &DTLSInfo::getVersion,
                        help_dtls_version)
                .def(self_ns::str(self_ns::self))
        ;

	boost::python::class_<QuicInfo, SharedPointer<QuicInfo>, boost::noncopyable>("QuicInfo",
		"Class that stores information of Quic.")
                .def_readonly("host_name", &QuicInfo::getServerName,
                        help_quic_host_name)
                .def_readonly("user_agent", &QuicInfo::getUserAgent,
                        help_quic_user_agent)
                .def_readonly("matched_domain_name", &QuicInfo::getMatchedDomainName,
                        help_quic_matched_domain_name)
                .def(self_ns::str(self_ns::self))
        ;

	boost::python::class_<DCERPCInfo, SharedPointer<DCERPCInfo>, boost::noncopyable>("DCERCPInfo",
		"Class that stores information of DCERPC.")
                .def_readonly("uuid", &DCERPCInfo::getUUID,
                        help_dcerpc_uuid)
                .def(self_ns::str(self_ns::self))
        ;

	boost::python::class_<SSHInfo, SharedPointer<SSHInfo>, boost::noncopyable>("SSHInfo",
		"Class that stores information of SSH.")
                .def_readonly("encrypted_bytes", &SSHInfo::getTotalEncryptedBytes,
                        help_ssh_encrypted_bytes)
                .def_readonly("server_name", &SSHInfo::getServerName,
                        help_ssh_server_name)
                .def_readonly("client_name", &SSHInfo::getClientName,
                        help_ssh_client_name)
                .def(self_ns::str(self_ns::self))
        ;

	boost::python::class_<DHCPv6Info, SharedPointer<DHCPv6Info>, boost::noncopyable>("DHCPv6Info",
		"Class that stores information of DHCPv6.")
                .def_readonly("host_name", &DHCPv6Info::getHostName,
                        help_dhcp6_info_name)
                .def_readonly("ip", &DHCPv6Info::getIPAddress,
                        help_dhcp6_info_ip)
                .def(self_ns::str(self_ns::self))
        ;

        boost::python::class_<SMBInfo, SharedPointer<SMBInfo>, boost::noncopyable>("SMBInfo",
		"Class that stores information of SMB.")
                .def_readonly("filename", &SMBInfo::getFilename,
                        help_smb_file_name)
                .def(self_ns::str(self_ns::self))
        ;

        boost::python::class_<DHCPInfo, SharedPointer<DHCPInfo>, boost::noncopyable>("DHCPInfo",
		"Class that stores information of DHCP.")
                .def_readonly("host_name", &DHCPInfo::getHostName,
                        help_dhcp_info_name)
                .def_readonly("ip", &DHCPInfo::getIPAddress,
                        help_dhcp_info_ip)
                .def(self_ns::str(self_ns::self))
        ;

        boost::python::class_<NetbiosInfo, SharedPointer<NetbiosInfo>, boost::noncopyable>("NetbiosInfo",
		"Class that stores information of Netbios.")
                .def_readonly("name", &NetbiosInfo::getNetbiosName,
                        help_netbios_info_name)
                .def(self_ns::str(self_ns::self))
        ;

        boost::python::class_<MQTTInfo, SharedPointer<MQTTInfo>, boost::noncopyable>("MQTTInfo",
		"Class that stores information of MQTT.")
                .def_readonly("topic", &MQTTInfo::getTopic,
                        help_mqtt_info_topic)
                .def(self_ns::str(self_ns::self))
        ;

        boost::python::class_<CoAPInfo, SharedPointer<CoAPInfo>, boost::noncopyable>("CoAPInfo",
		"Class that stores information of CoAP.")
                .def_readonly("uri", &CoAPInfo::getUri,
                        help_coap_info_uri)
                .def_readonly("host_name", &CoAPInfo::getHostName,
                        help_coap_info_host_name)
                .def_readonly("matched_domain_name", &CoAPInfo::getMatchedDomainName,
                        help_coap_info_matched_domain_name)
                .def(self_ns::str(self_ns::self))
        ;

        boost::python::class_<BitcoinInfo, SharedPointer<BitcoinInfo>, boost::noncopyable>("BitcoinInfo",
		"Class that stores information of Bitcoin.")
                .def_readonly("total_transactions", &BitcoinInfo::getTotalTransactions,
                        help_bitcoin_info_tx)
                .def_readonly("total_blocks", &BitcoinInfo::getTotalBlocks,
                        help_bitcoin_info_blocks)
                .def_readonly("total_rejects", &BitcoinInfo::getTotalRejects,
                        help_bitcoin_info_rejects)
                .def(self_ns::str(self_ns::self))
        ;

	boost::python::class_<DNSInfo, SharedPointer<DNSInfo>, boost::noncopyable>("DNSInfo",
		"Class that stores information of DNS.")
		.def("__iter__", boost::python::range(&DNSInfo::begin, &DNSInfo::end),
			help_dns_info_iter)
		.def_readonly("query_type", &DNSInfo::getQueryType,
			help_dns_info_query_type)
		.def_readonly("domain_name", &DNSInfo::getDomainName,
			help_dns_info_domain_name)
                .def_readonly("matched_domain_name", &DNSInfo::getMatchedDomainName,
                        help_dns_info_matched_domain_name)
                .def_readonly("txid", &DNSInfo::getTransactionId,
                        help_dns_info_txid)
                .def_readonly("ttl", &DNSInfo::getTTL,
                        help_dns_info_ttl)
                .def_readonly("rcode", &DNSInfo::getResponseCode,
                        help_dns_info_rcode)
		.def(self_ns::str(self_ns::self))
	;

        boost::python::class_<SSLInfo, SharedPointer<SSLInfo>, boost::noncopyable>("SSLInfo",
		"Class that stores information of SSL.")
                .def_readonly("server_name", &SSLInfo::getServerName,
                        help_ssl_info_server_name)
                .def_readonly("issuer_name", &SSLInfo::getIssuerName,
                        help_ssl_info_issuer_name)
                .def_readonly("cipher", &SSLInfo::getCipher,
                        help_ssl_info_cipher)
                .def_readonly("session_id", &SSLInfo::getSessionId,
                        help_ssl_info_session_id)
                .def_readonly("matched_domain_name", &SSLInfo::getMatchedDomainName,
                        help_ssl_info_matched_domain_name)
#if defined(HAVE_JA3)
                .def_readonly("fingerprint", &SSLInfo::getFingerprint,
                        help_ssl_info_fingerprint)
#endif
                .def(self_ns::str(self_ns::self))
        ;

	boost::python::class_<HTTPInfo, SharedPointer<HTTPInfo>, boost::noncopyable>("HTTPInfo",
		"Class that stores information of HTTP.")
                .def_readonly("total_requests", &HTTPInfo::getTotalRequests,
                        help_http_info_total_reqs)
                .def_readonly("total_responses", &HTTPInfo::getTotalResponses,
                        help_http_info_total_res)
                .def_readonly("uri", &HTTPInfo::getUri,
                        help_http_info_uri)
                .def_readonly("host_name", &HTTPInfo::getHostName,
                        help_http_info_host_name)
                .def_readonly("user_agent", &HTTPInfo::getUserAgent,
                        help_http_info_user_agent)
                .def_readonly("content_type", &HTTPInfo::getContentType,
                        help_http_info_content_type)
                .add_property("banned", &HTTPInfo::isBanned, &HTTPInfo::setBanAndRelease,
                        help_http_info_banned)
                .def_readonly("matched_domain_name", &HTTPInfo::getMatchedDomainName,
                        help_http_info_matched_domain_name)
                .def(self_ns::str(self_ns::self))
	;

	void (HTTPUriSet::*showURIs)() const                  =       &HTTPUriSet::show;
	
        boost::python::class_<HTTPUriSet, SharedPointer<HTTPUriSet>, boost::noncopyable>("HTTPUriSet",
		"Class that handles HTTP URI sets.")
		.def(init<>())
		.def(init<const std::string&>())
		.def("__len__", &HTTPUriSet::getTotalURIs,
			help_http_uri_set_uris)
                .add_property("callback", &HTTPUriSet::getCallback, &HTTPUriSet::setCallback,
                        help_http_uri_set_callback)
		.def_readonly("lookups", &HTTPUriSet::getTotalLookups,
			help_http_uri_set_lookups)
		.def_readonly("lookups_in", &HTTPUriSet::getTotalLookupsIn,
			help_http_uri_set_lookups_in)
		.def_readonly("lookups_out", &HTTPUriSet::getTotalLookupsOut,
			help_http_uri_set_lookups_out)
                .def("add_uri", &HTTPUriSet::addURI,
                        help_http_uri_set_add_uri)
                .def("show", showURIs,
                        help_http_uri_set_show_uris)
		.def(self_ns::str(self_ns::self))
        ;

        boost::python::class_<SIPInfo, SharedPointer<SIPInfo>, boost::noncopyable>("SIPInfo",
		"Class that stores information of SIP.")
                .def_readonly("uri", &SIPInfo::getUri,
                        help_sip_info_uri)
                .def_readonly("from_name", &SIPInfo::getFrom,
                        help_sip_info_from_name)
                .def_readonly("to_name", &SIPInfo::getTo,
                        help_sip_info_to_name)
                .def_readonly("via", &SIPInfo::getVia,
                        help_sip_info_via)
		.def(self_ns::str(self_ns::self))
        ;
	
        boost::python::class_<SMTPInfo, SharedPointer<SMTPInfo>, boost::noncopyable>("SMTPInfo",
		"Class that stores information of SMTP.")
                .def_readonly("mail_from", &SMTPInfo::getFrom,
                        help_smtp_info_mail_from)
                .def_readonly("mail_to", &SMTPInfo::getTo,
                        help_smtp_info_mail_to)
		.add_property("banned", &SMTPInfo::isBanned, &SMTPInfo::setIsBanned,
                        help_smtp_info_banned)
		.def(self_ns::str(self_ns::self))
        ;

        boost::python::class_<POPInfo, SharedPointer<POPInfo>, boost::noncopyable>("POPInfo",
		"Class that stores information of POP.")
                .def_readonly("user_name", &POPInfo::getUserName,
                        help_pop_info_user_name)
		.def(self_ns::str(self_ns::self))
        ;

       	boost::python::class_<IMAPInfo, SharedPointer<IMAPInfo>, boost::noncopyable>("IMAPInfo",
		"Class that stores information of IMAP.")
                .def_readonly("user_name", &IMAPInfo::getUserName,
                        help_imap_info_user_name)
		.def(self_ns::str(self_ns::self))
        ;

        boost::python::class_<SSDPInfo, SharedPointer<SSDPInfo>, boost::noncopyable>("SSDPInfo",
		"Class that stores information of SSDP.")
                .def_readonly("uri", &SSDPInfo::getUri,
                        help_ssdp_info_uri)
                .def_readonly("host_name", &SSDPInfo::getHostName,
                        help_ssdp_info_host_name)
                .def(self_ns::str(self_ns::self))
        ;

        boost::python::class_<TCPInfo, SharedPointer<TCPInfo>, boost::noncopyable>("TCPInfo",
		"Class that stores information of TCP.")
                .def_readonly("syns", &TCPInfo::getTotalSyns,
                        help_tcp_info_syns)
                .def_readonly("synacks", &TCPInfo::getTotalSynAcks,
                        help_tcp_info_synacks)
                .def_readonly("acks", &TCPInfo::getTotalAcks,
                        help_tcp_info_acks)
                .def_readonly("fins", &TCPInfo::getTotalFins,
                        help_tcp_info_fins)
                .def_readonly("rsts", &TCPInfo::getTotalRsts,
                        help_tcp_info_rsts)
                .def_readonly("pushs", &TCPInfo::getTotalPushs,
                        help_tcp_info_pushs)
                .def_readonly("state", &TCPInfo::getState,
                        help_tcp_info_state)
                .def(self_ns::str(self_ns::self))
        ;

	boost::python::class_<Frequencies, SharedPointer<Frequencies>, boost::noncopyable>("Frequencies",
		"Class that stores information of Frequencies.")
		.def_readonly("dispersion", &Frequencies::getDispersion,
			help_frequencies_dispersion)
		.def_readonly("entropy", &Frequencies::getEntropy,
			help_frequencies_enthropy)
		.def_readonly("frequencies", &Frequencies::getFrequenciesString,
			help_frequencies_get_freq_string)
		.def(self_ns::str(self_ns::self))
	;
	
	boost::python::class_<PacketFrequencies, SharedPointer<PacketFrequencies>, boost::noncopyable>("PacketFrequencies",
		"Class that stores information of PacketFrequencies.")
		.def_readonly("packet_frequencies", &PacketFrequencies::getPacketFrequenciesString,
			help_packet_frequencies_get_freq)
		.def(self_ns::str(self_ns::self))
	;

        boost::python::class_<DomainName, SharedPointer<DomainName>, boost::noncopyable>("DomainName",
		"Class that manages a domain and the behavior.",
		init<const std::string&, const std::string&>())
		.def(init<const std::string&, const std::string&, boost::python::object>())
                .def_readonly("expression", &DomainName::getExpression,
			help_domain_name_expresion)
                .def_readonly("name", &DomainName::name,
			help_domain_name_name)
                .def_readonly("matchs", &DomainName::getMatchs,
			help_domain_name_matchs)
                .add_property("callback", &DomainName::getCallback, &DomainName::setCallback,
			help_domain_name_callback)
		.add_property("http_uri_set", &DomainName::getPyHTTPUriSet, &DomainName::setPyHTTPUriSet,
			help_domain_name_http_uri_set)
		.add_property("http_uri_regex_manager", &DomainName::getPyHTTPUriRegexManager, &DomainName::setPyHTTPUriRegexManager,
			help_domain_name_http_uri_rm)
		.add_property("regex_manager", &DomainName::getPyHTTPRegexManager, &DomainName::setPyHTTPRegexManager,
			help_domain_name_regex_manager)
		.def(self_ns::str(self_ns::self))
        ;

        void (DomainNameManager::*addDomainName1)(const std::string&, const std::string&) = 	&DomainNameManager::addDomainName;
        void (DomainNameManager::*addDomainName2)(const SharedPointer<DomainName>&) = 		&DomainNameManager::addDomainName;
	void (DomainNameManager::*statisticsDomain)() =						&DomainNameManager::statistics;
	void (DomainNameManager::*showsByName)(const std::string&) =				&DomainNameManager::statistics;
	void (DomainNameManager::*showMatchedDomains)() const =					&DomainNameManager::showMatchedDomains;
        void (DomainNameManager::*setDomainNameManagerName)(const std::string&) = 		&DomainNameManager::name;
	const char* (DomainNameManager::*getDomainNameManagerName)() const =			&DomainNameManager::name;

        boost::python::class_<DomainNameManager, SharedPointer<DomainNameManager>, boost::noncopyable >("DomainNameManager",
		"Class that manages Domain Names.")
		.def(init<>())
		.def(init<const std::string&>())
		.def(init<boost::python::list&>())
		.def(init<const std::string&, boost::python::list&>())
		.add_property("name", getDomainNameManagerName, setDomainNameManagerName,
			help_domain_name_mng_name)
                .def("add_domain_name", addDomainName1,
			help_domain_name_mng_add_domain_n)
                .def("add_domain_name", addDomainName2,
			help_domain_name_mng_add_domain)
		.def("remove_domain_name", &DomainNameManager::removeDomainNameByName,
			help_domain_name_mng_remove_dom_n)
		.def("__len__", &DomainNameManager::getTotalDomains,
			help_domain_name_mng_len)
		.def("show", statisticsDomain,
			help_domain_name_mng_show)
		.def("show", showsByName,
			help_domain_name_mng_show_n)
		.def("show_matched_domains", showMatchedDomains, 
			help_domain_name_mng_show_matchs)
		.def("reset", &DomainNameManager::resetStatistics, 
			help_domain_name_mng_reset)
        ;

        boost::python::class_<DatabaseAdaptorWrap, boost::noncopyable>("DatabaseAdaptor",
		"Abstract class for implements connections with databases", no_init)
                .def("connect", pure_virtual(&DatabaseAdaptor::connect),
			help_adaptor_connect)
                .def("insert", pure_virtual(&DatabaseAdaptor::insert),
			help_adaptor_insert)
                .def("update", pure_virtual(&DatabaseAdaptor::update),
			help_adaptor_update)
                .def("remove", pure_virtual(&DatabaseAdaptor::remove),
			help_adaptor_remove)
        ;

        boost::python::class_<IPAbstractSet, boost::noncopyable>("IPAbstractSet",
		"Abstract class for implements searchs on IP addresses", no_init)
                .def("add_ip_address", pure_virtual(&IPAbstractSet::addIPAddress),
			help_ip_abstract_set_add_ip)
	;

	void (IPSet::*showIPAddresses)() const			=	&IPSet::show;
        void (IPSet::*setIPSetName)(const std::string&) = 		&IPSet::name;
	const char* (IPSet::*getIPSetName)() const =			&IPSet::name;

	boost::python::class_<IPSet, bases<IPAbstractSet>, SharedPointer<IPSet>>("IPSet",
		"Class that stores and manages IP addresses on a set.")
		.def(init<>())
		.def(init<const std::string&>())
		.def(init<boost::python::list&>())
		.def(init<const std::string&, boost::python::list&>())
		.def(init<const std::string&, boost::python::list&, boost::python::object>())
                .add_property("name", getIPSetName, setIPSetName,
			help_ip_set_name)
                .def_readonly("lookups", &IPSet::getTotalLookups,
                        help_ip_set_lookups)
                .def_readonly("lookups_in", &IPSet::getTotalLookupsIn,
                        help_ip_set_lookups_in)
                .def_readonly("lookups_out", &IPSet::getTotalLookupsOut,
                        help_ip_set_lookups_out)
		.add_property("callback", &IPSet::getCallback, &IPSet::setCallback,
			help_ip_set_callback)
		.add_property("regex_manager", &IPSet::getRegexManager, &IPSet::setRegexManager,
			help_ip_set_regex_manager)
		.def("add_ip_address", &IPSet::addIPAddress,
			help_ip_set_add_ip)
		.def("remove_ip_address", &IPSet::removeIPAddress,
			help_ip_set_remove_ip)
		.def("show", showIPAddresses,
			help_ip_set_show)
		.def("__len__", &IPSet::getTotalIPs,
			help_ip_set_len)
		.def(self_ns::str(self_ns::self))
	;

	void (IPRadixTree::*showRadixIPAddresses)() 			=	&IPRadixTree::show;
        void (IPRadixTree::*setIPRadixTreeName)(const std::string&) = 		&IPRadixTree::name;
	const char* (IPRadixTree::*getIPRadixTreeName)() const =		&IPRadixTree::name;

        boost::python::class_<IPRadixTree, bases<IPAbstractSet>, SharedPointer<IPRadixTree>>("IPRadixTree",
		"Class that stores and manages IP addresses on a radix tree.")
                .def(init<>())
                .def(init<const std::string&>())
		.def(init<boost::python::list&>())
		.def(init<const std::string&, boost::python::list&>())
                .add_property("name", getIPRadixTreeName, setIPRadixTreeName,
                        help_iprad_set_name)
                .def_readonly("lookups", &IPRadixTree::getTotalLookups,
                        help_iprad_set_lookups)
                .def_readonly("lookups_in", &IPRadixTree::getTotalLookupsIn,
                        help_iprad_set_lookups_in)
                .def_readonly("lookups_out", &IPRadixTree::getTotalLookupsOut,
                        help_iprad_set_lookups_out)
		.add_property("callback", &IPRadixTree::getCallback, &IPRadixTree::setCallback,
			help_iprad_set_callback)
		.add_property("regex_manager", &IPRadixTree::getRegexManager, &IPRadixTree::setRegexManager,
			help_iprad_set_regex_manager)
                .def("add_ip_address", &IPRadixTree::addIPAddress,
                        help_iprad_set_add_ip)
                .def("remove_ip_address", &IPRadixTree::removeIPAddress,
                        help_iprad_set_remove_ip)
		.def("show", showRadixIPAddresses,
			help_iprad_set_show)
                .def("__len__", &IPRadixTree::getTotalIPs,
                        help_iprad_set_len)
		.def(self_ns::str(self_ns::self))
        ;

#ifdef HAVE_BLOOMFILTER
        boost::python::class_<IPBloomSet, bases<IPAbstractSet>, SharedPointer<IPBloomSet>>("IPBloomSet",
		"Class that stores and manages IP addresses on a bloomset.")
                .def(init<>())
                .def(init<const std::string&>())
                .add_property("callback", &IPBloomSet::getCallback, &IPBloomSet::setCallback,
			help_ip_bloom_set_callback)
                .def("add_ip_address", &IPBloomSet::addIPAddress,
			help_ip_bloom_set_add_ip)
                .def("__len__", &IPBloomSet::getTotalIPs,
			help_ip_bloom_set_len)
        ;

#endif // HAVE_BLOOMFILTER

	void (IPSetManager::*addIPSet)(const SharedPointer<IPAbstractSet>&) = 		&IPSetManager::addIPSet;
	void (IPSetManager::*removeIPSet)(const SharedPointer<IPAbstractSet>&) = 	&IPSetManager::removeIPSet;
	void (IPSetManager::*removeIPSetByName)(const std::string&) = 			&IPSetManager::removeIPSet;
	void (IPSetManager::*showsIPSetManager)() = 					&IPSetManager::statistics;
	void (IPSetManager::*showsByNameIPSetManager)(const std::string&) =		&IPSetManager::statistics;
        void (IPSetManager::*setIPSetManagerName)(const std::string&) = 		&IPSetManager::name;
	const char* (IPSetManager::*getIPSetManagerName)() const =			&IPSetManager::name;

        boost::python::class_<IPSetManager, SharedPointer<IPSetManager>, boost::noncopyable>("IPSetManager",
		"Class that stores and manages IPSets, IPRadixTrees and IPBloomSets.")
		.def(init<>())
		.def(init<const std::string&>())
		.def("__iter__", boost::python::range(&IPSetManager::begin, &IPSetManager::end),
			help_ip_set_manager_iter)
                .add_property("name", getIPSetManagerName, setIPSetManagerName,
                        help_ip_set_manager_name)
                .def("add_ip_set", addIPSet,
			help_ip_set_manager_add_ip)
                .def("remove_ip_set", removeIPSet,
			help_ip_set_manager_del_ip)
                .def("remove_ip_set", removeIPSetByName,
			help_ip_set_manager_del_ip_name)
		.def("__len__", &IPSetManager::getTotalSets,
			help_ip_set_manager_len)
		.def("show", showsIPSetManager,
			help_ip_set_manager_show)
		.def("show", showsByNameIPSetManager,
			help_ip_set_manager_show_name)
		.def("reset", &IPSetManager::resetStatistics,
			help_ip_set_manager_reset)
        ;

	void (FrequencyGroup<std::string>::*FGstatistics)() const =			&FrequencyGroup<std::string>::statistics;

	boost::python::class_<FrequencyGroup<std::string>>("FrequencyGroup",
		"Class that manages and compute frequencies.")
                .def_readonly("total_process_flows", &FrequencyGroup<std::string>::getTotalProcessFlows,
			help_freq_group_tot_proc_flows)
		.def_readonly("total_computed_frequencies", &FrequencyGroup<std::string>::getTotalComputedFrequencies,
			help_freq_group_tot_comp_freq)
		.def("add_flows_by_source_port", &FrequencyGroup<std::string>::agregateFlowsBySourcePort,
			help_freq_group_add_by_src_port)
		.def("add_flows_by_destination_port", &FrequencyGroup<std::string>::agregateFlowsByDestinationPort,
			help_freq_group_add_by_dst_port)
		.def("add_flows_by_source_address", &FrequencyGroup<std::string>::agregateFlowsBySourceAddress,
			help_freq_group_add_by_src_addr)
		.def("add_flows_by_destination_address", &FrequencyGroup<std::string>::agregateFlowsByDestinationAddress,
			help_freq_group_add_by_dst_addr)
		.def("add_flows_by_destination_address_and_port", &FrequencyGroup<std::string>::agregateFlowsByDestinationAddressAndPort,
			help_freq_group_add_by_dst_p_a)
		.def("add_flows_by_source_address_and_port", &FrequencyGroup<std::string>::agregateFlowsBySourceAddressAndPort,
			help_freq_group_add_by_src_p_a)
		.def("add_all_flows", &FrequencyGroup<std::string>::agregateAllFlows,
			help_freq_group_add_all)
		.def("compute", &FrequencyGroup<std::string>::compute,
			help_freq_group_compute)
		.def("reset", &FrequencyGroup<std::string>::reset,
			help_freq_group_reset)
		.def("get_reference_flows_by_key", &FrequencyGroup<std::string>::getReferenceFlowsByKey,
			help_freq_group_get_ref_flow_k)
		.def("get_reference_flows", &FrequencyGroup<std::string>::getReferenceFlows,
			help_freq_group_get_ref_flow)
		.def("show", FGstatistics,
			help_freq_group_show)
	;

        boost::python::class_<LearnerEngine, SharedPointer<LearnerEngine>>("LearnerEngine",
		"Class that generates regular expressions.")
		.def_readonly("flows_process", &LearnerEngine::getTotalFlowsProcess,
			help_learn_flows_proc)
                .def_readonly("regex", &LearnerEngine::getRegularExpression,
			help_learn_regex)
                .def("agregate_flows", &LearnerEngine::agregateFlows,
			help_learn_agregate_flows)
                .def("compute", &LearnerEngine::compute,
			help_learn_compute)
                .def("reset", &LearnerEngine::reset,
			help_learn_reset)
                .def(self_ns::str(self_ns::self))
        ;

	void (Cache<StringCache>::*show)() const = 		&Cache<StringCache>::statistics;

	boost::python::class_<Cache<StringCache>, SharedPointer<Cache<StringCache>>>("Cache",
                "This class manages the internal allocated memory of different object types manage by a protocol.")
                .def_readonly("total_items", &Cache<StringCache>::getTotal,
			help_cache_total_items)
                .def_readonly("total_acquires", &Cache<StringCache>::getTotalAcquires,
			help_cache_total_acquires)
                .def_readonly("total_releases", &Cache<StringCache>::getTotalReleases,
			help_cache_total_releases)
                .def_readonly("total_fails", &Cache<StringCache>::getTotalFails,
			help_cache_total_fails)
		.add_property("dynamic_allocated_memory", &Cache<StringCache>::isDynamicAllocatedMemory, &Cache<StringCache>::setDynamicAllocatedMemory,
			help_cache_dynamic_memory)
                .def("show", show,
			help_cache_show)
                .def("create", &Cache<StringCache>::create,
			help_cache_create)
                .def("destroy", &Cache<StringCache>::destroy,
			help_cache_destroy)
                .def("reset", &Cache<StringCache>::reset,
			help_cache_reset)
        ;
}

